package com.wisenet.controller.client.paynotify;

import java.io.IOException;
import java.util.SortedMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.alibaba.fastjson.JSON;
import com.wisenet.annotation.LoginValidate;
import com.wisenet.cache.SimpleCacheProvider;
import com.wisenet.common.PayConst;
import com.wisenet.entity.SportWearOrder;
import com.wisenet.entity.WeixinPubno;
import com.wisenet.pojo.WxPayResult;
import com.wisenet.service.sportwear.SportWearOrderService;
import com.wisenet.wx.tenpay.http.util.WeiXinPayUtil;

/**
 * 运动服微信支付回调：用户取消支付不进入回调
 * @author fzh
 *
 */
@Controller
public class SportWearPayNotifyController {
	private static final Logger logger = LoggerFactory.getLogger(SportWearPayNotifyController.class);

	@Autowired
	private SportWearOrderService orderService;
	@Autowired
	private SimpleCacheProvider simpleCacheProvider;
	// 对象锁
	private final Object lock = new Object();
	
	@LoginValidate(value = false)
	@RequestMapping(value = "/sportWearNotify", produces = "application/json;charset=UTF-8")
	protected void notify(HttpServletRequest request, HttpServletResponse response) {
		logger.info("wxpay callback begin...");
		try {
			synchronized (lock) {
				// 获取回调报文xml
				SortedMap<String, String> map = WeiXinPayUtil.getNotifyXml(request.getReader());
				if (map == null) return;
				
				// 验证签名、验证订单和金额、处理支付回调结果、更新次数
				String resultXml = validateAndDealData(map);
				// 回调结果给微信
				WeiXinPayUtil.sendResultXmlToWX(resultXml, response.getOutputStream());
				logger.info("wxpay callback end.");
			}
		} catch (Exception ex) {
			logger.error("wxpay callback error: " + ex.getMessage());
		}
	}

	/**
	 * 1、验证签名
	 * 2、验证支付金额
	 * 3、处理支付回调结果
	 * @param map
	 * @return
	 */
	public String validateAndDealData(SortedMap<String, String> map) {
		// 1成功，2失败
		int status = PayConst.PAY_STATUS_FAIL;
		// 默认返回成功，防止微信重复通知
		String resultXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
						+ "<return_msg><![CDATA[OK]]></return_msg>" + "</xml>";
		
		// 处理支付请求
		WxPayResult wxPayResult;
		try {
			wxPayResult = WeiXinPayUtil.toCamelObject(JSON.toJSONString(map), WxPayResult.class);
		} catch (IOException e) {
			logger.error("fail: toCamelObject convert error...");
			wxPayResult = new WxPayResult();
			wxPayResult.setReturnCode(PayConst.FAIL);
		}
		if (PayConst.FAIL.equals(wxPayResult.getReturnCode())) {
			logger.error("fail: " + wxPayResult.getReturnMsg());
			resultXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
								+ "<return_msg><![CDATA[return_code is FAIL]]></return_msg>" + "</xml>";
			return resultXml;
		}
		
		// 查询订单
		SportWearOrder order = orderService.findByUidAndOutTradeNo(wxPayResult.getOpenid(), wxPayResult.getOutTradeNo());
		// 处理微信重复通知
		if (order == null) {
			logger.error("the order is null, reject wx notify!");
			return resultXml;
		}
		if (PayConst.PAY_STATUS_SUCCESS.equals(order.getPayStatus())) {
			logger.info("the order status is success, reject wx notify!");
			return resultXml;
		}
		
		WeixinPubno weixinPubno = simpleCacheProvider.get(wxPayResult.getAppid());
		if (weixinPubno == null) {
			resultXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
					  + "<return_msg><![CDATA[APP is NULL]]></return_msg>" + "</xml>";
			return resultXml;
		}
		
		// 1、验证签名
		boolean valid = WeiXinPayUtil.validateSignature(map, weixinPubno.getMchKey());
		if (!valid) {
			logger.error("sign is wrong!");
			// 更新订单状态
			orderService.updateOrderStatus(order.getId(), status, order.getUid(), "签名验证失败");
			resultXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
								+ "<return_msg><![CDATA[sign is wrong]]></return_msg>" + "</xml>";
			return resultXml;
		}

		// 2、验证支付金额
		if (PayConst.SUCCESS.equals(wxPayResult.getResultCode())) {
			boolean moneyCorrect = validateMoney(wxPayResult, order);
			if (!moneyCorrect) {
				resultXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
						+ "<return_msg><![CDATA[支付金额不一致]]></return_msg>" + "</xml>";
				return resultXml;
			}
			// 支付成功
			status = PayConst.PAY_STATUS_SUCCESS;
			resultXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
					+ "<return_msg><![CDATA[OK]]></return_msg>" + "</xml>";
			// 4、更新订单状态
			orderService.updateOrderStatus(order.getId(), status, order.getUid(), "支付成功");
			return resultXml;
		}
		// 支付失败
		logger.error("wxpay fail: " + wxPayResult.getErrCodeDes());
		resultXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
				+ "<return_msg><![CDATA[pay fail]]></return_msg>" + "</xml>";
		return resultXml;
	}
	
	/**
	 * 验证金额
	 * @param result
	 * @param order
	 * @return
	 */
	public boolean validateMoney(WxPayResult result, SportWearOrder order) {
		double totalFee = order.getTotalPrice() * 100;
		if (result.getTotalFee() != (int) totalFee) {
			// 更新订单状态
			orderService.updateOrderStatus(order.getId(), PayConst.PAY_STATUS_FAIL, order.getUid(), "订单金额不一致");
			logger.info(result.getOpenid() + " " + result.getOutTradeNo());
			logger.info("mydb-totalFee: " + (int) totalFee + " wxpay-totalFee: " + result.getTotalFee());
			return false;
		}
		return true;
	}

}
